在 JS 中有監聽器 addeventListener ,而 Vue 也有自己一套 DOM 元素監聽器的指令 v-on , Vue 也配置了幾個修飾符來替代像是 preventDefault() 、 stopPropagation() 等等的。
v-on 指令執行簡單事件
<!--v-on:事件=執行事件-->
<button type="button" v-on:click="count++">數字加1</button>
v-on:click="count++" 就是指當 <button> 元素發生 click 事件,就執行 count++ 。
執行複雜事件
方法一:綁定方法
<!--v-on:事件=執行事件-->
<button type="button" v-on:click="greet">數字加1</button>
<script>
const vm = new Vue({
el:'#vm',
data:{
userName:'Celeste'
},
methods:{
greet(){
alert(`Hello ${this.userName}`)
}
}
})
</script>
把複雜的事件處理方法寫在 methods 裡,在讓 v-on 接收這個方法,如 greet ,在接收時,該方法並不需要加上 ()。
當事件(click)發生時,執行的方法預設有 event 物件,所以無須將 event 設為參數。
方法二:調用方法
Vue 提供 $event 屬性,可以用來取得 DOM event 物件的值。
<!--v-on:事件=執行事件-->
<button type="button" v-on:click="greet2('Celeste',$event)">數字加1</button>
<script>
const vm = new Vue({
el:'#vm',
methods:{
greet2(name,event){
alert(`Hello ${name}`)
console.log(event)
}
}
})
</script>
<!--v-on:事件=執行事件-->
<button type="button" v-on:click="greet">數字加1</button>
<script>
const vm = new Vue({
el:'#vm',
data:{
userName:'Celeste'
},
methods:{
greet(){
alert(`Hello ${this.userName}`)
}
}
})
</script>
v-on 指令在 JS 中,可以透過一些方法來阻止一些預設行為,像是 event.preventDefault() 、 event.stopPropagation() 或是改變事件傳遞的階段,而 Vue 透過加入修飾符也能達到相同的作用。
Vue 提供的修飾符:
.stop.stop 跟 JS 裡 event.stopPropagation() 目的相同,阻止後續的事件傳遞。
<div class="changeTarget" v-on:click.stop="changeTarget('div')">
<button type="button" v-on:click.stop="changeTarget('button')">changeTarget</button>
</div>
在沒有 .stop 的情況,如果點擊 <button> ,則上層 <div> 跟 <button>皆會觸發 changeTarget(),這是因為事件的傳遞預設為 Bubbling ,所以在觸發 changeTarget('button') 後,會接續觸發 changeTarget('div') ,而修飾符 .stop 就是當第一個事件執行後,後續的冒泡事件又或是捕獲事件就會被阻止。
.prevent.prevent 跟 JS 裡 event.preventDefault() 目的相同,阻止元素的預設行為,像是 <a> 跟 <button> 的預設行為會導致頁面跳轉或重整。
<a href="https://www.google.com/" target="_blank" v-on:click.prevent="changeTarget('a')" >changeTarget</a>
.capture
在 JS 中, addEventListener 事件傳遞預設是 Bubbling,如果要變成 Capturing ,就需要將第三個參數改成 true。
在 Vue 裡,如果想把觸發時機點改成 Capturing ,可以直接使用修飾符 .capture。
<div class="changeTarget" v-on:click.capture="changeTarget('div')">
<button type="button" v-on:click.stop="changeTarget('button')">changeTarget</button>
</div>
.self
在 Vue 文件說明裡,可以知道當元素事件監聽加入修飾符 .self 後,只有當這個元素是 AT_TARGET 階段(透過 event.eventPhase 查詢,值為2)才能觸發該元素的事件。
<!-- only trigger handler if event.target is the element itself -->
<div class="changeTarget" v-on:click.self="changeTarget('div')">
<span class="changeTarget" v-on:click="changeTarget('innerSpan')">
<button type="button" v-on:click="changeTarget('button')">changeTarget</button>
</span>
</div>
跟 .capture.stop 比較
<!-- only trigger handler if event.target is the element itself -->
<div class="changeTarget" v-on:click.capture.self="changeTarget('div')">
<span class="changeTarget" v-on:click.capture.stop="changeTarget('innerSpan')">
<button type="button" v-on:click="changeTarget('button')">changeTarget</button>
</span>
</div>
.capture.stop 是指元素在捕獲階段執行完事件並阻止後續元素的事件發生,但該元素的 event.eventPhase 值還是 1 ,但 .self 是指元素只有在 event.eventPhase 值是 2 的情況才能被執行,所以即使設定 <div class="changeTarget" v-on:click.capture.self="changeTarget('div')"></div> 在捕獲階段執行事件,但因為 <div> 的 event.eventPhase 值是 1 ,所以事件不被執行。
.once
使用修飾符 .once ,該事件只能被執行1次。
<div class="changeTarget" v-on:click.once="changeTarget('div')">
<span class="changeTarget" v-on:click.once="changeTarget('innerSpan')">
<button type="button" v-on:click.once="changeTarget('button')">changeTarget</button>
</span>
</div>
.passive
看了 MDN 對於參數 passive 的介紹,主要是針對 touch 某些事件在 scrolling 事件發生時,會有停頓延遲的情況,參數 passive 預設是 false ,當參數 passive 改為 true 時,可以改善scrolling 事件停頓延遲這個問題。
MDN-Improving scrolling performance with passive listeners
Improving Scroll Performance with Passive Event Listeners
v-on 指令透過加入按鍵修飾符,以決定使用哪個按鍵來執行事件。
常見的幾個按鍵修飾符如下:
.enter
.tab
.delete (“删除”和“退格”鍵).esc
.space
.up
.down
.left
.right
.ctrl
.alt
.shift
單一按鍵修飾符
<input type="text" v-on:keyup.enter="addTodo" v-model="newTodo">
監聽鍵盤中 enter 按鍵的 keyup 事件,當 enter 按鍵被按下再鬆開後就會去執行所綁定的函式 addTodo。
多個按鍵修飾符
<input type="text" v-on:keyup.alt.67="clear" v-model="newTodo">
監聽鍵盤中 alt 跟 C 按鍵的 keyup 事件,必須特別注意的是當 .alt、.ctrl、shift 等修飾鍵與其他按鍵或事件組合時,事件要觸發的話, .alt、.ctrl、shift 等修飾鍵是必須處於按下的狀態的,例如同時按下 alt 跟 C 按鍵,並不會觸發 clear 事件,按下 alt 跟 C 按鍵後僅放開 alt 按鍵,也不會觸發事件,只有在按下 alt 跟 C 按鍵後放開 C 按鍵( alt 按鍵仍須持續按著)才會觸發事件。
同理
<button type="button" v-on:click.ctrl="addTodo">addTodo</button>
如果要觸發事件必須是 ctrl 按鍵持續按著並點擊按鈕才能觸發事件。
v-on 指令加入滑鼠按鈕修飾符的狀況下,只有那個滑鼠按鈕才能觸發事件。
.left
.right
.middle
<button type="button" v-on:click.right="addTodo">addTodo</button>
Demo:[DAY08]跟 Vue.js 認識的30天 - Vue 的事件監聽
參考資料: